home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cfengine-1.5.3 / src / edittools.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-07-28  |  35.0 KB  |  1,349 lines

  1. /* cfengine for GNU
  2.  
  3.         Copyright (C) 1995
  4.         Free Software Foundation, Inc.
  5.  
  6.    This file is part of GNU cfengine - written and maintained 
  7.    by Mark Burgess, Dept of Computing and Engineering, Oslo College,
  8.    Dept. of Theoretical physics, University of Oslo
  9.  
  10.    This program is free software; you can redistribute it and/or modify it
  11.    under the terms of the GNU General Public License as published by the
  12.    Free Software Foundation; either version 2, or (at your option) any
  13.    later version.
  14.  
  15.    This program is distributed in the hope that it will be useful,
  16.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.    GNU General Public License for more details.
  19.  
  20.   You should have received a copy of the GNU General Public License
  21.   along with this program; if not, write to the Free Software
  22.   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
  23.  
  24. */
  25.  
  26.  
  27. /********************************************************************/
  28. /*                                                                  */
  29. /* EDITING of simple textfiles (Toolkit)                            */
  30. /*                                                                  */
  31. /********************************************************************/
  32.  
  33. #include "cf.defs.h"
  34. #include "cf.extern.h"
  35.  
  36. /********************************************************************/
  37. /* EDIT Data structure routines                                     */
  38.  
  39. /********************************************************************/
  40.  
  41. DoEditHomeFiles(ptr)
  42.  
  43. struct Edit *ptr;
  44.  
  45. { DIR *dirh, *dirh2;
  46.   struct dirent *dirp, *dirp2;
  47.   char username[maxvarsize], *sp;
  48.   char homedir[bufsize],dest[bufsize];
  49.   struct passwd *pw;
  50.   struct stat statbuf;
  51.   struct Item *ip;
  52.   uid_t uid;
  53.   
  54. if (!MountPathDefined())
  55.    {
  56.    CfLog(cfinform,"Mountpattern is undefined\n","");
  57.    return;
  58.    }
  59.  
  60. for (ip = VMOUNTLIST; ip != NULL; ip=ip->next)
  61.    {
  62.    if (IsExcluded(ip->classes))
  63.       {
  64.       continue;
  65.       }
  66.    
  67.    if ((dirh = opendir(ip->name)) == NULL)
  68.       {
  69.       sprintf(OUTPUT,"Can't open directory %s\n",ip->name);
  70.       CfLog(cferror,OUTPUT,"opendir");
  71.       return;
  72.       }
  73.  
  74.    for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
  75.       {
  76.       if (!SensibleFile(dirp->d_name,ip->name,NULL))
  77.          {
  78.          continue;
  79.          }
  80.  
  81.       strcpy(homedir,ip->name);
  82.       AddSlash(homedir);
  83.       strcat(homedir,dirp->d_name);
  84.  
  85.       if (! IsHomeDir(homedir))
  86.          {
  87.          continue;
  88.          }
  89.  
  90.       if ((dirh2 = opendir(homedir)) == NULL)
  91.          {
  92.          sprintf(OUTPUT,"Can't open directory%s\n",homedir);
  93.          CfLog(cferror,OUTPUT,"opendir");
  94.          return;
  95.          }
  96.  
  97.       for (dirp2 = readdir(dirh2); dirp2 != NULL; dirp2 = readdir(dirh2))
  98.          {
  99.          if (!SensibleFile(dirp2->d_name,homedir,NULL))
  100.         {
  101.         continue;
  102.         }
  103.  
  104.          strcpy(username,dirp2->d_name);
  105.          strcpy(dest,homedir);
  106.          AddSlash(dest);
  107.          strcat(dest,dirp2->d_name);
  108.          AddSlash(dest);
  109.          sp = ptr->fname + strlen("home/");
  110.          strcat(dest,sp);
  111.  
  112.          if (stat(dest,&statbuf))
  113.             {
  114.             Verbose("%s: file %s doesn't exist for editing, skipping\n",VPREFIX,dest);
  115.             continue;
  116.             }
  117.       
  118.          if ((pw = getpwnam(username)) == NULL)
  119.             {
  120.             Debug2("cfengine: directory corresponds to no user %s - ignoring\n",username);
  121.             continue;
  122.             }
  123.          else
  124.             {
  125.             Debug2("(Setting user id to %s)\n",username);
  126.             }
  127.  
  128.          uid = statbuf.st_uid;
  129.  
  130.          WrapDoEditFile(ptr,dest);
  131.       
  132.          chown(dest,uid,sameowner);
  133.          }
  134.       closedir(dirh2);
  135.       }
  136.    closedir(dirh);
  137.    }
  138. }
  139.  
  140. /********************************************************************/
  141.  
  142. WrapDoEditFile(ptr)
  143.  
  144. struct Edit *ptr;
  145.  
  146. { struct stat statbuf,statbuf2;
  147.   char linkname[bufsize];
  148.   char realname[bufsize];
  149.  
  150. Debug("WrapDoEditFile(%s)\n",ptr->fname);
  151.   
  152. if (lstat(ptr->fname,&statbuf) != -1)
  153.    {
  154.    if (S_ISLNK(statbuf.st_mode))
  155.       {
  156.       Verbose("%s: File %s is a link, editing real file instead\n",VPREFIX,ptr->fname);
  157.       
  158.       bzero(linkname,bufsize);
  159.       bzero(realname,bufsize);
  160.       
  161.       if (readlink(ptr->fname,linkname,bufsize) == -1)
  162.      {
  163.      sprintf(OUTPUT,"Cannot read link %s\n",ptr->fname);
  164.      CfLog(cferror,OUTPUT,"readlink");
  165.      return;
  166.      }
  167.       
  168.       if (linkname[0] != '/')
  169.      {
  170.      strcpy(realname,ptr->fname);
  171.      ChopLastNode(realname);
  172.      AddSlash(realname);
  173.      }
  174.       
  175.       if (BufferOverflow(realname,linkname))
  176.      {
  177.      sprintf(OUTPUT,"(culprit %s in editfiles)\n",ptr->fname);
  178.      CfLog(cferror,OUTPUT,"");
  179.      return;
  180.      }
  181.       
  182.       if (stat(ptr->fname,&statbuf2) != -1)
  183.      {
  184.      if (statbuf2.st_uid != statbuf.st_uid)
  185.         {
  186.         /* Link to /etc/passwd? ouch! */
  187.         sprintf(OUTPUT,"Forbidden to edit a link to another user's file with privilege (%s)",ptr->fname);
  188.         CfLog(cfinform,OUTPUT,"");
  189.         return;
  190.         }
  191.      }
  192.       
  193.       strcat(realname,linkname);
  194.       DoEditFile(ptr,realname);
  195.       }
  196.    else
  197.       {
  198.       DoEditFile(ptr,ptr->fname);
  199.       }
  200.    }
  201. else
  202.    {
  203.    DoEditFile(ptr,ptr->fname);
  204.    }
  205. }
  206.  
  207. /********************************************************************/
  208.  
  209. DoEditFile(ptr,filename)
  210.  
  211. struct Edit *ptr;
  212. char *filename;
  213.  
  214.  
  215.    /* Many of the functions called here are defined in the */
  216.    /* item.c toolkit since they operate on linked lists    */
  217.  
  218. { struct Edlist *ep, *loopstart, *loopend, *ThrowAbort();
  219.   struct Item *filestart = NULL, *newlineptr;
  220.   char *currenteditscript, *searchstr;
  221.   struct stat tmpstat;
  222.   char spliton = ':';
  223.   int todo = 0;
  224.   int foreachloop = false;
  225.   FILE *loop_fp;
  226.  
  227. Debug("DoEditFile(%s)\n",filename);
  228. filestart = NULL;
  229. currenteditscript = NULL;
  230. searchstr = NULL;
  231. bzero(ACTIONBUFF,bufsize);
  232. AUTOCREATED = false;
  233. IMAGEBACKUP = true;
  234.  
  235. for (ep = ptr->actions; ep != NULL; ep=ep->next)
  236.    {
  237.    if (!IsExcluded(ep->classes))
  238.       {
  239.       todo++;
  240.       }
  241.    }
  242.  
  243. if (todo == 0)   /* Because classes are stored per edit, not per file */
  244.    {
  245.    return;
  246.    }
  247.  
  248. if (!GetLock(ASUniqueName("editfile"),CanonifyName(ptr->fname),VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  249.    {
  250.    return;
  251.    }
  252.  
  253. CheckEditSwitches(filename,ptr->actions);
  254.  
  255. if (! LoadItemList(&filestart,filename))
  256.    {
  257.    CfLog(cfverbose,"File was marked for editing\n","");
  258.    ReleaseCurrentLock();
  259.    return;
  260.    }
  261.  
  262. NUMBEROFEDITS = 0;
  263. EDITVERBOSE = VERBOSE;
  264. CURRENTLINENUMBER = 1;
  265. CURRENTLINEPTR = filestart;
  266. COMMENTSTART = "# ";
  267. COMMENTEND = "";
  268. EDITGROUPLEVEL = 0;
  269. SEARCHREPLACELEVEL = 0;
  270. FOREACHLEVEL = 0;
  271. loopstart = NULL;
  272.  
  273. Verbose("%s: Begin editing %s\n",VPREFIX,filename);
  274. ep = ptr->actions;
  275.  
  276. while (ep != NULL)
  277.    {
  278.    if (IsExcluded(ep->classes))
  279.       {
  280.       ep = ep->next;
  281.       continue;
  282.       }
  283.  
  284.    Debug2("Edit action: %s\n",VEDITNAMES[ep->code]);
  285.  
  286.    switch(ep->code)
  287.       {
  288.       case NoEdit:
  289.       case AutoCreate:
  290.                break;
  291.  
  292.       case CatchAbort:
  293.               EditVerbose("%s: Caught Exception\n",VPREFIX);
  294.               break;
  295.  
  296.       case SplitOn:
  297.               spliton = *(ep->data);
  298.           EditVerbose("%s: Split lines by %c\n",VPREFIX,spliton);
  299.           break;
  300.  
  301.       case DeleteLinesStarting:
  302.                while (DeleteItemStarting(&filestart,ep->data))
  303.                   {
  304.                   }
  305.                break;
  306.  
  307.       case DeleteLinesContaining:
  308.                while (DeleteItemContaining(&filestart,ep->data))
  309.                   {
  310.                   }
  311.                break;
  312.  
  313.       case DeleteLinesAfterThisMatching:
  314.  
  315.                if ((filestart == NULL) || (CURRENTLINEPTR == NULL))
  316.           {
  317.           break;
  318.           }
  319.            else if (CURRENTLINEPTR->next != NULL)
  320.           {
  321.                   while (DeleteItemMatching(&(CURRENTLINEPTR->next),ep->data))
  322.                     {
  323.                }
  324.           }
  325.                break;           
  326.  
  327.       case DeleteLinesMatching:
  328.                while (DeleteItemMatching(&filestart,ep->data))
  329.                  {
  330.          }
  331.                break;
  332.            
  333.       case Append:
  334.               AppendItem(&filestart,ep->data,NULL);
  335.               break;
  336.  
  337.       case AppendIfNoSuchLine:
  338.                if (! IsItemIn(filestart,ep->data))
  339.                   {
  340.                   AppendItem(&filestart,ep->data,NULL);
  341.                   }
  342.                break;
  343.  
  344.       case SetLine:
  345.                strcpy(ACTIONBUFF,ep->data);
  346.                EditVerbose("%s: Set current line to %s\n",VPREFIX,ACTIONBUFF);
  347.                break;
  348.  
  349.       case AppendIfNoLineMatching:
  350.  
  351.                if (strcmp(ACTIONBUFF,"") == 0)
  352.                   {
  353.                   sprintf(OUTPUT,"%s: SetLine not set when calling AppendIfNoLineMatching %s\n",VPREFIX,ep->data);
  354.           CfLog(cferror,OUTPUT,"");
  355.                   continue;
  356.                   }
  357.            
  358.                if (LocateNextItemMatching(filestart,ep->data) == NULL)
  359.               {
  360.                   AppendItem(&filestart,ACTIONBUFF,NULL);
  361.                   }
  362.                break;
  363.  
  364.       case Prepend:
  365.                PrependItem(&filestart,ep->data,NULL);
  366.                break;
  367.  
  368.       case PrependIfNoSuchLine:
  369.                if (! IsItemIn(filestart,ep->data))
  370.                   {
  371.                   PrependItem(&filestart,ep->data,NULL);
  372.                   }
  373.                break;
  374.  
  375.       case PrependIfNoLineMatching:
  376.  
  377.                if (strcmp(ACTIONBUFF,"") == 0)
  378.                   {
  379.                   printf("%s: SetLine not set when calling PrependIfNoLineMatching %s\n",VPREFIX,ep->data);
  380.                   continue;
  381.                   }
  382.  
  383.                if (LocateNextItemMatching(filestart,ep->data) == NULL)
  384.                   {
  385.                   PrependItem(&filestart,ACTIONBUFF,NULL);
  386.                   }
  387.                break;
  388.  
  389.       case WarnIfNoSuchLine:
  390.                if (LocateNextItemMatching(filestart,ep->data) == NULL)
  391.                   {
  392.                   printf("%s: Warning, file %s has no line matching %s\n",VPREFIX,filename,ep->data);
  393.                   }
  394.                break;
  395.  
  396.       case WarnIfLineMatching:
  397.                if (LocateNextItemMatching(filestart,ep->data) != NULL)
  398.                   {
  399.                   printf("%s: Warning, file %s has a line matching %s\n",VPREFIX,filename,ep->data);
  400.                   }
  401.                break;
  402.  
  403.       case WarnIfNoLineMatching:
  404.                if (LocateNextItemMatching(filestart,ep->data) == NULL)
  405.                   {
  406.                   printf("%s: Warning, file %s has a no line matching %s\n",VPREFIX,filename,ep->data);
  407.                   }
  408.                break;
  409.  
  410.       case WarnIfLineStarting:
  411.                if (LocateNextItemStarting(filestart,ep->data) != NULL)
  412.                   {
  413.                   printf("%s: Warning, file %s has a line starting %s\n",VPREFIX,filename,ep->data);
  414.                   }
  415.                break;
  416.  
  417.       case WarnIfNoLineStarting:
  418.                if (LocateNextItemStarting(filestart,ep->data) == NULL)
  419.                   {
  420.                   printf("%s: Warning, file %s has no line starting %s\n",VPREFIX,filename,ep->data);
  421.                   }
  422.                break;
  423.  
  424.       case WarnIfLineContaining:
  425.                if (LocateNextItemContaining(filestart,ep->data) != NULL)
  426.                   {
  427.                   printf("%s: Warning, file %s has a line containing %s\n",VPREFIX,filename,ep->data);
  428.                   }
  429.                break;
  430.  
  431.       case WarnIfNoLineContaining:
  432.                if (LocateNextItemContaining(filestart,ep->data) == NULL)
  433.                   {
  434.                   printf("%s: Warning, file %s has no line containing %s\n",VPREFIX,filename,ep->data);
  435.                   }
  436.                break;
  437.  
  438.       case SetCommentStart:
  439.                COMMENTSTART = ep->data;
  440.                break;
  441.  
  442.       case SetCommentEnd:
  443.                COMMENTEND = ep->data;
  444.                break;
  445.  
  446.       case CommentLinesMatching:
  447.                while (CommentItemMatching(&filestart,ep->data,COMMENTSTART,COMMENTEND))
  448.                   {
  449.                   }
  450.                break;
  451.  
  452.       case CommentLinesStarting:
  453.                while (CommentItemStarting(&filestart,ep->data,COMMENTSTART,COMMENTEND))
  454.                   {
  455.                   }
  456.                break;
  457.  
  458.       case CommentLinesContaining:
  459.                while (CommentItemContaining(&filestart,ep->data,COMMENTSTART,COMMENTEND))
  460.                   {
  461.                   }
  462.                break;
  463.  
  464.       case HashCommentLinesContaining:
  465.                while (CommentItemContaining(&filestart,ep->data,"# ",""))
  466.                   {
  467.                   }
  468.                break;
  469.  
  470.       case HashCommentLinesStarting:
  471.                while (CommentItemStarting(&filestart,ep->data,"# ",""))
  472.                   {
  473.                   }
  474.                break;
  475.  
  476.       case HashCommentLinesMatching:
  477.                while (CommentItemMatching(&filestart,ep->data,"# ",""))
  478.                   {
  479.                   }
  480.                break;
  481.  
  482.       case SlashCommentLinesContaining:
  483.                while (CommentItemContaining(&filestart,ep->data,"//",""))
  484.                   {
  485.                   }
  486.                break;
  487.  
  488.       case SlashCommentLinesStarting:
  489.                while (CommentItemStarting(&filestart,ep->data,"//",""))
  490.                   {
  491.                   }
  492.                break;
  493.  
  494.       case SlashCommentLinesMatching:
  495.                while (CommentItemMatching(&filestart,ep->data,"//",""))
  496.                   {
  497.                   }
  498.                break;
  499.  
  500.       case PercentCommentLinesContaining:
  501.                while (CommentItemContaining(&filestart,ep->data,"%",""))
  502.                   {
  503.                   }
  504.                break;
  505.  
  506.       case PercentCommentLinesStarting:
  507.                while (CommentItemStarting(&filestart,ep->data,"%",""))
  508.                   {
  509.                   }
  510.                break;
  511.  
  512.       case PercentCommentLinesMatching:
  513.                while (CommentItemMatching(&filestart,ep->data,"%",""))
  514.                   {
  515.                   }
  516.                break;
  517.  
  518.       case ResetSearch:
  519.                if (!ResetEditSearch(ep->data,filestart))
  520.                   {
  521.                   printf("%s: ResetSearch Failed in %s, aborting editing\n",VPREFIX,filename);
  522.                   goto abort;
  523.                   }
  524.                break;
  525.  
  526.       case LocateLineMatching:
  527.                newlineptr = LocateItemMatchingRegExp(CURRENTLINEPTR,ep->data);
  528.  
  529.                if (newlineptr == NULL)
  530.                   {
  531.                   EditVerbose("%s: LocateLineMatchingRegexp failed in %s, aborting editing\n",VPREFIX,filename);
  532.                   ep = ThrowAbort(ep);
  533.                   }
  534.                break;
  535.  
  536.       case InsertLine:
  537.               if (filestart == NULL)
  538.              {
  539.              AppendItem(&filestart,ep->data,NULL);
  540.              }
  541.           else
  542.              {
  543.              InsertItemAfter(&filestart,CURRENTLINEPTR,ep->data);
  544.              }
  545.                   break;
  546.  
  547.       case InsertFile:
  548.               InsertFileAfter(&filestart,CURRENTLINEPTR,ep->data);
  549.           break;
  550.  
  551.       case IncrementPointer:
  552.                if (! IncrementEditPointer(ep->data,filestart))     /* edittools */
  553.                   {
  554.                   printf ("%s: IncrementPointer failed in %s, aborting editing\n",VPREFIX,filename);
  555.                 ep = ThrowAbort(ep);
  556.                   }
  557.  
  558.                break;
  559.            
  560.      case ReplaceLineWith:
  561.                if (!ReplaceEditLineWith(ep))
  562.                   {
  563.                   printf("%s: aborting edit of file %s\n",VPREFIX,filename);
  564.                   continue;
  565.                   }
  566.                break;
  567.  
  568.       case DeleteToLineMatching:
  569.                if (! DeleteToRegExp(&filestart,ep->data))
  570.                   {
  571.                   EditVerbose("%s: Nothing matched DeleteToLineMatching regular expression\n",VPREFIX);
  572.                   EditVerbose("%s: Aborting file editing of %s.\n",VPREFIX ,filename);
  573.                   ep = ThrowAbort(ep);
  574.                   }
  575.                break;
  576.  
  577.       case DeleteNLines:
  578.                if (! DeleteSeveralLines(&filestart,ep->data))
  579.                   {
  580.                   EditVerbose("%s: Could not delete %s lines from file\n",VPREFIX,ep->data);
  581.                   EditVerbose("%s: Aborting file editing of %s.\n",VPREFIX,filename);
  582.                   ep = ThrowAbort(ep);
  583.                   }
  584.                break;
  585.  
  586.       case HashCommentToLineMatching:
  587.                if (! CommentToRegExp(&filestart,ep->data,"#",""))
  588.                   {
  589.                   EditVerbose("%s: Nothing matched HashCommentToLineMatching regular expression\n",VPREFIX);
  590.                   EditVerbose("%s: Aborting file editing of %s.\n",VPREFIX,filename);
  591.                   ep = ThrowAbort(ep);
  592.                   }
  593.                break;
  594.  
  595.       case PercentCommentToLineMatching:
  596.                if (! CommentToRegExp(&filestart,ep->data,"%",""))
  597.                   {
  598.                   EditVerbose("%s: Nothing matched PercentCommentToLineMatching regular expression\n",VPREFIX);
  599.                   EditVerbose("%s: Aborting file editing of %s.\n",VPREFIX,filename);
  600.                   ep = ThrowAbort(ep);
  601.                   }
  602.                break;
  603.  
  604.       case CommentToLineMatching:
  605.                if (! CommentToRegExp(&filestart,ep->data,COMMENTSTART,COMMENTEND))
  606.                   {
  607.                   EditVerbose("%s: Nothing matched CommentToLineMatching regular expression\n",VPREFIX);
  608.                   EditVerbose("%s: Aborting file editing of %s.\n",VPREFIX,filename);
  609.                   ep = ThrowAbort(ep);
  610.                   }
  611.                break;
  612.  
  613.       case CommentNLines:
  614.                if (! CommentSeveralLines(&filestart,ep->data,COMMENTSTART,COMMENTEND))
  615.                   {
  616.                   EditVerbose("%s: Could not comment %s lines from file\n",VPREFIX,ep->data);
  617.                   EditVerbose("%s: Aborting file editing of %s.\n",VPREFIX,filename);
  618.                   ep = ThrowAbort(ep);
  619.                   }
  620.                break;
  621.            
  622.       case UnCommentNLines:
  623.                if (! UnCommentSeveralLines(&filestart,ep->data,COMMENTSTART,COMMENTEND))
  624.                   {
  625.                   EditVerbose("%s: Could not comment %s lines from file\n",VPREFIX,ep->data);
  626.                   EditVerbose("%s: Aborting file editing of %s.\n",VPREFIX,filename);
  627.                   ep = ThrowAbort(ep);
  628.                   }
  629.                break;
  630.  
  631.       case UnCommentLinesContaining:
  632.                while (UnCommentItemContaining(&filestart,ep->data,COMMENTSTART,COMMENTEND))
  633.                   {
  634.                   }
  635.                break;
  636.  
  637.       case UnCommentLinesMatching:
  638.                while (UnCommentItemMatching(&filestart,ep->data,COMMENTSTART,COMMENTEND))
  639.                   {
  640.                   }
  641.                break;
  642.            
  643.       case SetScript:
  644.                currenteditscript = ep->data;
  645.                break;
  646.  
  647.       case RunScript:
  648.                if (! RunEditScript(ep->data,filename,&filestart))
  649.                   {
  650.                   printf("%s: Aborting further edits to %s\n",VPREFIX,filename);
  651.                   ep = ThrowAbort(ep);
  652.                   }
  653.                break;
  654.  
  655.       case RunScriptIfNoLineMatching:
  656.                if (! LocateNextItemMatching(filestart,ep->data))
  657.                   {
  658.                   if (! RunEditScript(currenteditscript,filename,&filestart))
  659.                      {
  660.                      printf("%s: Aborting further edits to %s\n",VPREFIX,filename);
  661.                      ep = ThrowAbort(ep);
  662.                      }
  663.                   }
  664.                break;
  665.  
  666.       case RunScriptIfLineMatching:
  667.                if (LocateNextItemMatching(filestart,ep->data))
  668.                   {
  669.                   if (! RunEditScript(currenteditscript,filename,&filestart))
  670.                      {
  671.                      printf("%s: Aborting further edits to %s\n",VPREFIX,filename);
  672.                      ep = ThrowAbort(ep);
  673.                      }
  674.                   }
  675.                break;
  676.  
  677.       case EmptyEntireFilePlease:
  678.                EditVerbose("Emptying entire file\n");
  679.                DeleteItemList(filestart);
  680.            filestart = NULL;
  681.            CURRENTLINEPTR = NULL;
  682.            CURRENTLINENUMBER=0;
  683.                NUMBEROFEDITS++;
  684.                break;
  685.  
  686.       case GotoLastLine:
  687.                GotoLastItem(filestart);
  688.                break;
  689.  
  690.       case BreakIfLineMatches:
  691.                if (LineMatches(CURRENTLINEPTR->name,ep->data))
  692.                   {
  693.                   EditVerbose("Break! %s\n",ep->data);
  694.                   goto abort;
  695.                   }
  696.                break;
  697.  
  698.       case BeginGroupIfNoMatch:
  699.            if (CURRENTLINEPTR == NULL || CURRENTLINEPTR->name == NULL )
  700.           {
  701.           EditVerbose("(Begin Group - no match for %s - file empty)\n",ep->data);
  702.           break;
  703.           }
  704.            
  705.                if (LineMatches(CURRENTLINEPTR->name,ep->data))
  706.                   {
  707.                   EditVerbose("(Begin Group - skipping %s)\n",ep->data);
  708.                   while(ep->code != EndGroup)
  709.                      {
  710.                      ep=ep->next;
  711.                      }
  712.                   }
  713.                else
  714.                   {
  715.                   EditVerbose("(Begin Group - no match for %s)\n",ep->data);
  716.                   }
  717.                break;
  718.  
  719.      case BeginGroupIfNoLineMatching:
  720.                if (LocateItemMatchingRegExp(filestart,ep->data) != 0)
  721.                   {
  722.                   EditVerbose("(Begin Group - skipping)\n");
  723.                   while(ep->code != EndGroup)
  724.                      {
  725.                      ep=ep->next;
  726.                      }
  727.                   }
  728.                else
  729.                   {
  730.                   EditVerbose("(Begin Group - no line matching %s)\n",ep->data);
  731.                   }
  732.                break;
  733.  
  734.       case BeginGroupIfNoLineContaining:
  735.                if (LocateNextItemContaining(filestart,ep->data) != 0)
  736.                   {
  737.                   EditVerbose("(Begin Group - skipping, string matched)\n");
  738.                   while(ep->code != EndGroup)
  739.                      {
  740.                      ep=ep->next;
  741.                      }
  742.                   }
  743.                else
  744.                   {
  745.                   EditVerbose("(Begin Group - no line containing %s)\n",ep->data);
  746.                   }
  747.                break;
  748.  
  749.       case BeginGroupIfNoSuchLine:
  750.                if (IsItemIn(filestart,ep->data))
  751.                   {
  752.                   EditVerbose("(Begin Group - skipping, line exists)\n");
  753.                   while(ep->code != EndGroup)
  754.                      {
  755.                      ep=ep->next;
  756.                      }
  757.                   }
  758.                else
  759.                   {
  760.                   EditVerbose("(Begin Group - no line %s)\n",ep->data);
  761.                   }
  762.                break;
  763.  
  764.  
  765.      case BeginGroupIfFileIsNewer:
  766.                if ((!AUTOCREATED) && (!FileIsNewer(filename,ep->data)))
  767.                   {
  768.                   EditVerbose("(Begin Group - skipping, file is older)\n");
  769.                   while(ep->code != EndGroup)
  770.                      {
  771.                      ep=ep->next;
  772.                      }
  773.                   }
  774.                else
  775.                   {
  776.                   EditVerbose("(Begin Group - new file %s)\n",ep->data);
  777.                   }
  778.                break;
  779.  
  780.      case BeginGroupIfFileExists:
  781.                if (stat(ep->data,&tmpstat) == -1)
  782.                   {
  783.                   EditVerbose("(Begin Group - file unreadable/no such file - skipping)\n");
  784.                   while(ep->code != EndGroup)
  785.                      {
  786.                      ep=ep->next;
  787.                      }
  788.                   }
  789.                else
  790.                   {
  791.                   EditVerbose("(Begin Group - found file %s)\n",ep->data);
  792.                   }
  793.                break;
  794.       case EndGroup:
  795.                EditVerbose("(End Group)\n");
  796.                break;
  797.  
  798.       case ReplaceAll:
  799.                searchstr = ep->data;
  800.                break;
  801.  
  802.       case With:
  803.                GlobalReplace(&filestart,searchstr,ep->data);
  804.                break;
  805.  
  806.       case FixEndOfLine:
  807.                DoFixEndOfLine(filestart,ep->data);
  808.            break;
  809.  
  810.       case AbortAtLineMatching:
  811.                EDABORTMODE = true;
  812.            strcpy(VEDITABORT,ep->data);
  813.            break;
  814.  
  815.       case UnsetAbort:
  816.                EDABORTMODE = false;
  817.            break;
  818.  
  819.       case AutoMountDirectResources:
  820.            HandleAutomountRescources(&filestart,ep->data);
  821.            break;
  822.  
  823.       case ForEachLineIn:
  824.            if (loopstart == NULL)
  825.           {
  826.               loopstart = ep;
  827.  
  828.           if ((loop_fp = fopen(ep->data,"r")) == NULL)
  829.              {
  830.              EditVerbose("Couldn't open %s\n",ep->data);
  831.              while(ep->code != EndLoop) /* skip over loop */
  832.                 {
  833.                 ep = ep->next;
  834.                 }
  835.              break;
  836.              }
  837.           
  838.           EditVerbose("Starting ForEach loop with %s\n",ep->data);
  839.           continue;
  840.           }
  841.            else
  842.           {
  843.               if (!feof(loop_fp))
  844.              {
  845.              bzero(ACTIONBUFF,bufsize);
  846.              ReadLine(ACTIONBUFF,bufsize,loop_fp); /* Like SetLine */
  847.              }
  848.           else
  849.              {
  850.              EditVerbose("EndForeach\n");
  851.              
  852.              fclose(loop_fp);
  853.              loopstart = NULL;
  854.              
  855.              while(ep->code != EndLoop)
  856.                 {
  857.                 ep = ep->next;
  858.                 }
  859.              }
  860.           }
  861.            
  862.            break;
  863.  
  864.       case EndLoop:
  865.            loopend = ep;
  866.               ep = loopstart;
  867.            continue;
  868.  
  869.       case ReplaceLinesMatchingField:
  870.            ReplaceWithFieldMatch(&filestart,ep->data,ACTIONBUFF,spliton,filename);
  871.            break;
  872.  
  873.       case AppendToLineIfNotContains:
  874.            AppendToLine(CURRENTLINEPTR,ep->data,filename);
  875.            break;
  876.  
  877.       case DefineClasses:
  878.            break;
  879.  
  880.       default: printf("%s: Unknown action in editing of file %s\n",VPREFIX,filename);
  881.                break;
  882.       }
  883.  
  884.    ep = ep->next;
  885.    }
  886.  
  887. abort :  
  888.  
  889. EditVerbose("%s: End editing %s\n",VPREFIX,filename);
  890. EditVerbose(".....................................................................\n");
  891.  
  892. EDITVERBOSE = false;
  893.  
  894. if (DONTDO || CompareToFile(filestart,filename))
  895.    {
  896.    NUMBEROFEDITS = 0;
  897.    }
  898.  
  899. if ((! DONTDO) && (NUMBEROFEDITS > 0))
  900.    {
  901.    SaveItemList(filestart,filename);
  902.    AddEditfileClasses(ptr);
  903.    }
  904.  
  905. ResetOutputRoute('d','d');
  906. ReleaseCurrentLock();
  907.  
  908. DeleteItemList(filestart);
  909. }
  910.  
  911. /********************************************************************/
  912.  
  913. IncrementEditPointer(str,liststart)
  914.  
  915. char *str;
  916. struct Item *liststart;
  917.  
  918. { int i,n = 0;
  919.   struct Item *ip;
  920.  
  921. sscanf(str,"%d", &n);
  922.  
  923. if (n == 0)
  924.    {
  925.    printf("%s: Illegal increment value: %s\n",VPREFIX,str);
  926.    return false;
  927.    }
  928.  
  929. Debug("IncrementEditPointer(%d)\n",n);
  930.  
  931. if (CURRENTLINEPTR == NULL)  /* is prev undefined, set to line 1 */
  932.    {
  933.    if (liststart == NULL)
  934.       {
  935.       EditVerbose("cannot increment line pointer in empty file\n");
  936.       return true;
  937.       }
  938.    else
  939.       {
  940.       CURRENTLINEPTR=liststart;
  941.       CURRENTLINENUMBER=1;
  942.       }
  943.    }
  944.  
  945.  
  946. if (n < 0)
  947.    {
  948.    if (CURRENTLINENUMBER + n < 1)
  949.       {
  950.       EditVerbose("%s: pointer decrements to before start of file!\n",VPREFIX);
  951.       EditVerbose("%s: pointer stopped at start of file!\n",VPREFIX);
  952.       CURRENTLINEPTR=liststart;
  953.       CURRENTLINENUMBER=1;      
  954.       return true;
  955.       }
  956.  
  957.    i = 1;
  958.  
  959.    for (ip = liststart; ip != CURRENTLINEPTR; ip=ip->next, i++)
  960.       {
  961.       if (i == CURRENTLINENUMBER + n)
  962.          {
  963.          CURRENTLINENUMBER += n;
  964.          CURRENTLINEPTR = ip;
  965.      Debug2("Current line (%d) starts: %20.20s ...\n",CURRENTLINENUMBER,CURRENTLINEPTR->name);
  966.  
  967.          return true;
  968.          }
  969.       }
  970.    }
  971.  
  972. for (i = 0; i < n; i++)
  973.    {
  974.    if (CURRENTLINEPTR->next != NULL)
  975.       {
  976.       CURRENTLINEPTR = CURRENTLINEPTR->next;
  977.       CURRENTLINENUMBER++;
  978.  
  979.       EditVerbose("incrementing line pointer to line %d\n",CURRENTLINENUMBER);
  980.       }
  981.    else
  982.       {
  983.       EditVerbose("inc pointer failed, still at %d\n",CURRENTLINENUMBER);
  984.       }
  985.    }
  986.  
  987. Debug2("Current line starts: %20s ...\n",CURRENTLINEPTR->name);
  988.  
  989. return true;
  990. }
  991.  
  992. /********************************************************************/
  993.  
  994. ResetEditSearch (str,list)
  995.  
  996. char *str;
  997. struct Item *list;
  998.  
  999. { int i = 1 ,n = -1;
  1000.   struct Item *ip;
  1001.  
  1002. sscanf(str,"%d", &n);
  1003.  
  1004. if (n < 1)
  1005.    {
  1006.    printf("%s: Illegal reset value: %s\n",VPREFIX,str);
  1007.    return false;
  1008.    }
  1009.  
  1010. for (ip = list; (i < n) && (ip != NULL); ip=ip->next, i++)
  1011.    {
  1012.    }
  1013.  
  1014. if (i < n || ip == NULL)
  1015.    {
  1016.    printf("%s: Search for (%s) begins after end of file!!\n",VPREFIX,str);
  1017.    return false;
  1018.    }
  1019.  
  1020. EditVerbose("resetting pointers to line %d\n",n);
  1021.  
  1022. CURRENTLINENUMBER = n;
  1023. CURRENTLINEPTR = ip;
  1024.  
  1025. return true;
  1026. }
  1027.  
  1028. /********************************************************************/
  1029.  
  1030. ReplaceEditLineWith (editptr)
  1031.  
  1032. struct Edlist *editptr;
  1033.  
  1034. { char *sp;
  1035.  
  1036. if (strcmp(editptr->data,CURRENTLINEPTR->name) == 0)
  1037.    {
  1038.    EditVerbose("ReplaceLineWith - line does not need correction.\n");
  1039.    return true;
  1040.    }
  1041.  
  1042. if ((sp = malloc(strlen(editptr->data)+1)) == NULL)
  1043.    {
  1044.    printf("%s: Memory allocation failed in ReplaceEditLineWith, aborting edit.\n",VPREFIX);
  1045.    return false;
  1046.    }
  1047.  
  1048. EditVerbose("Replacing line %d with %10s...\n",CURRENTLINENUMBER,editptr->data);
  1049. strcpy(sp,editptr->data);
  1050. free (CURRENTLINEPTR->name);
  1051. CURRENTLINEPTR->name = sp;
  1052. NUMBEROFEDITS++;
  1053. return true;
  1054. }
  1055.  
  1056. /********************************************************************/
  1057.  
  1058. RunEditScript (script,fname,filestart)
  1059.  
  1060. char *script, *fname;
  1061. struct Item **filestart;
  1062.  
  1063. { FILE *pp;
  1064.   char buffer[bufsize];
  1065.  
  1066. if (script == NULL)
  1067.    {
  1068.    printf("%s: No script defined for with SetScript\n",VPREFIX);
  1069.    return false;
  1070.    }
  1071.  
  1072. if (DONTDO)
  1073.    {
  1074.    return true;
  1075.    }
  1076.  
  1077. if (NUMBEROFEDITS > 0)
  1078.    {
  1079.    SaveItemList(*filestart,fname);
  1080.    }
  1081.  
  1082. DeleteItemList(*filestart);
  1083.  
  1084. sprintf (buffer,"%s %s %s  2>&1",script,fname,CLASSTEXT[VSYSTEMHARDCLASS]);
  1085.  
  1086. EditVerbose("Running command: %s\n",buffer);
  1087.  
  1088. if ((pp = popen(buffer,"r")) == NULL)
  1089.    {
  1090.    printf("%s: edit script %s failed to open.\n",VPREFIX,fname);
  1091.    return false;
  1092.    }
  1093.  
  1094. while (!feof(pp))   
  1095.    {
  1096.    ReadLine(CURRENTITEM,bufsize,pp);
  1097.  
  1098.    if (!feof(pp))
  1099.       {
  1100.       EditVerbose("%s\n",CURRENTITEM);
  1101.       }
  1102.    }
  1103.  
  1104. pclose(pp);
  1105.  
  1106. *filestart = 0;
  1107.  
  1108. if (! LoadItemList(filestart,fname))
  1109.    {
  1110.    printf("          File was marked for editing\n");
  1111.    return false;
  1112.    }
  1113.  
  1114. NUMBEROFEDITS = 0;
  1115. CURRENTLINENUMBER = 1;
  1116. CURRENTLINEPTR = *filestart;
  1117. return true;
  1118. }
  1119.  
  1120. /************************************************************/
  1121.  
  1122. DoFixEndOfLine(list,type)  /* fix end of line char format */
  1123.  
  1124.   /* Assumes that extra_space macro allows enough space */
  1125.   /* in the allocated strings to add a few characters */
  1126.  
  1127. struct Item *list;
  1128. char *type;
  1129.  
  1130. { struct Item *ip;
  1131.   char *sp;
  1132.   int gotCR;
  1133.  
  1134. EditVerbose("Checking end of line conventions: type = %s\n",type);
  1135.  
  1136. if (strcmp("unix",type) == 0 || strcmp("UNIX",type) == 0)
  1137.    {
  1138.    for (ip = list; ip != NULL; ip=ip->next)
  1139.       {
  1140.       for (sp = ip->name; *sp != '\0'; sp++)
  1141.      {
  1142.      if (*sp == (char)13)
  1143.         {
  1144.         *sp = '\0';
  1145.         NUMBEROFEDITS++;
  1146.         }
  1147.      }
  1148.       }
  1149.    return;
  1150.    }
  1151.  
  1152. if (strcmp("dos",type) == 0 || strcmp("DOS",type) == 0)
  1153.    {
  1154.    for (ip = list; ip != NULL; ip = ip->next)
  1155.       {
  1156.       gotCR = false;
  1157.       
  1158.       for (sp = ip->name; *sp !='\0'; sp++)
  1159.      {
  1160.      if (*sp == (char)13)
  1161.         {
  1162.         gotCR = true;
  1163.         }
  1164.      }
  1165.  
  1166.       if (!gotCR)
  1167.      {
  1168.      *sp = (char)13;
  1169.      *(sp+1) = '\0';
  1170.      NUMBEROFEDITS++;
  1171.      }
  1172.       }
  1173.    return;
  1174.    }
  1175.  
  1176. printf("%s: Unknown file format: %s\n",VPREFIX,type);
  1177. }
  1178.  
  1179. /**************************************************************/
  1180.  
  1181. HandleAutomountRescources(filestart,opts)
  1182.  
  1183. struct Item **filestart;
  1184. char *opts;
  1185.  
  1186. { struct Item *ip;
  1187.   char buffer[bufsize];
  1188.   char *sp;
  1189.  
  1190. for (ip = VMOUNTABLES; ip != NULL; ip=ip->next)
  1191.    {
  1192.    for (sp = ip->name; *sp != ':'; sp++)
  1193.       {
  1194.       }
  1195.  
  1196.    sp++;
  1197.    sprintf(buffer,"%s\t%s\t%s",sp,opts,ip->name);
  1198.  
  1199.    if (LocateNextItemContaining(*filestart,sp) == NULL)
  1200.       {
  1201.       AppendItem(filestart,buffer,"");
  1202.       NUMBEROFEDITS++;
  1203.       }
  1204.    else
  1205.       {
  1206.       EditVerbose("have a server for %s\n",sp);
  1207.       }
  1208.    }
  1209. }
  1210.  
  1211. /**************************************************************/
  1212.  
  1213. CheckEditSwitches(filename,actions)
  1214.  
  1215. char *filename;
  1216. struct Edlist *actions;
  1217.  
  1218. { struct stat statbuf;
  1219.   struct Edlist *ep;
  1220.   char inform = 'd', log = 'd';
  1221.   int fd;
  1222.  
  1223. for (ep = actions; ep != NULL; ep=ep->next)
  1224.    {
  1225.    if (IsExcluded(ep->classes))
  1226.       {
  1227.       continue;
  1228.       }
  1229.  
  1230.    switch(ep->code)
  1231.       {
  1232.       case AutoCreate: if (!DONTDO)
  1233.                       {
  1234.               if (stat(filename,&statbuf) == -1)
  1235.                  {
  1236.                  if ((fd = creat(filename,0644)) == -1)
  1237.                 {
  1238.                 sprintf(OUTPUT,"Unable to create file %s\n",filename);
  1239.                 CfLog(cfinform,OUTPUT,"creat");
  1240.                 }
  1241.                  else
  1242.                 {
  1243.                 AUTOCREATED = true;
  1244.                 close(fd);
  1245.                 }
  1246.                  sprintf(OUTPUT,"Creating file %s, mode 644\n",filename);
  1247.                  CfLog(cfinform,OUTPUT,"");
  1248.                  return;
  1249.                  }
  1250.               }
  1251.                        break;
  1252.       
  1253.       case EditBackup: if (strcmp("false",ToLowerStr(ep->data)) == 0 || strcmp("off",ToLowerStr(ep->data)) == 0)
  1254.                       {
  1255.               IMAGEBACKUP = false;
  1256.                       }
  1257.                        break;
  1258.                
  1259.       case EditLog:    if (strcmp(ToLowerStr(ep->data),"true") == 0 || strcmp(ToLowerStr(ep->data),"on") == 0)
  1260.                       {
  1261.               log = 't';
  1262.               break;
  1263.               }
  1264.  
  1265.                        if (strcmp(ToLowerStr(ep->data),"false") == 0 || strcmp(ToLowerStr(ep->data),"off") == 0)
  1266.                           {
  1267.               log = 'f';
  1268.               break;
  1269.               }
  1270.  
  1271.       case EditInform: if (strcmp(ToLowerStr(ep->data),"true") == 0 || strcmp(ToLowerStr(ep->data),"on") == 0)
  1272.                       {
  1273.               inform = 't';
  1274.               break;
  1275.               }
  1276.  
  1277.                        if (strcmp(ToLowerStr(ep->data),"false") == 0 || strcmp(ToLowerStr(ep->data),"off") == 0)
  1278.                           {
  1279.               inform = 'f';
  1280.               break;
  1281.               }
  1282.  
  1283.       
  1284.       }
  1285.    }
  1286.  
  1287. ResetOutputRoute(log,inform);
  1288. }
  1289.  
  1290.  
  1291. /**************************************************************/
  1292. /* Level 3                                                    */
  1293. /**************************************************************/
  1294.  
  1295. AddEditfileClasses (list)
  1296.  
  1297. struct Edit *list;
  1298.  
  1299. { char *sp, currentitem[maxvarsize];
  1300.   struct Edlist *ep;
  1301.  
  1302. for (ep = list->actions; ep != NULL; ep=ep->next)
  1303.    {
  1304.    if (ep->code == DefineClasses)
  1305.       {
  1306.       break;
  1307.       }
  1308.    }
  1309.  
  1310. if (ep == NULL)
  1311.    {
  1312.    return;
  1313.    }
  1314.  
  1315. Debug("Entering AddEditfileClasses(%s)\n",ep->data);
  1316.  
  1317. for (sp = ep->data; *sp != '\0'; sp++)
  1318.    {
  1319.    currentitem[0] = '\0';
  1320.  
  1321.    sscanf(sp,"%[^,:.]",currentitem);
  1322.  
  1323.    sp += strlen(currentitem);
  1324.  
  1325.    AddClassToHeap(currentitem);
  1326.    }
  1327. }
  1328.  
  1329. /**************************************************************/
  1330.  
  1331. struct Edlist *ThrowAbort(from)
  1332.  
  1333. struct Edlist *from;
  1334.  
  1335. { struct Edlist *ep, *last;
  1336.  
  1337. for (ep = from; ep != NULL; ep=ep->next)
  1338.    {
  1339.    if (ep->code == CatchAbort)
  1340.       {
  1341.       return ep;
  1342.       }
  1343.    
  1344.    last = ep;
  1345.    }
  1346.  
  1347. return last; 
  1348. }
  1349.